package com.ben.xinyue.seckill.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ben.basic.exception.BaseResponse;
import com.ben.basic.exception.DefaultSuccessEnum;
import com.ben.basic.redis.service.RedissonService;
import com.ben.xinyue.seckill.access.AccessLimit;
import com.ben.xinyue.seckill.domain.entity.MiaoshaOrder;
import com.ben.xinyue.seckill.domain.entity.MiaoshaUser;
import com.ben.xinyue.seckill.domain.vo.GoodsVo;
import com.ben.xinyue.seckill.rabbitmq.MQConfig;
import com.ben.xinyue.seckill.rabbitmq.MiaoshaMessage;
import com.ben.xinyue.seckill.service.GoodsService;
import com.ben.xinyue.seckill.service.MiaoshaOrderService;
import com.ben.xinyue.seckill.service.OrderInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName: MiaoshaController
 * @Description: 秒杀
 * @author: xinyue
 * @date: 2020/9/9 8:41 下午
 * @version: 1.0.0
 */
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {

    private final GoodsService goodsService;
    private final RedissonService redissonService;
    private final MiaoshaOrderService miaoshaOrderService;
    private final OrderInfoService orderInfoService;
    private final AmqpTemplate amqpTemplate;


    private static volatile boolean isGlobalActivityOver = false;
    private static final ConcurrentHashMap<Long, Integer> stockMap = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<Long, Boolean> localOverMap = new ConcurrentHashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        List<GoodsVo> goodsVos = goodsService.listGoodsVo();
        if(CollectionUtils.isEmpty(goodsVos)){
            return;
        }
        for (GoodsVo goods : goodsVos){
            redissonService.getRBucket("kucun_"+goods.getId()).set(goods.getStockCount());
            stockMap.put(goods.getId(), goods.getStockCount());
            localOverMap.put(goods.getId(), false);
        }
    }

    public static int getGoodsStockOriginal(long goodsId){
        Integer stock = stockMap.get(goodsId);
        if(Objects.isNull(stock)){
            return 0;
        }
        return stock;
    }

    public static void setGlobalActivityOver(){
        isGlobalActivityOver = true;
    }

    public static boolean isGlobalActivityOver(){
        return isGlobalActivityOver;
    }

    @RequestMapping(value="/verifyCode", method=RequestMethod.GET)
    @ResponseBody
    public void getMiaoshaVerifyCod(HttpServletResponse response, MiaoshaUser user,
                                              @RequestParam("goodsId")long goodsId) throws Exception {

        BufferedImage image  = miaoshaOrderService.createVerifyCode(user, goodsId);
        OutputStream out = response.getOutputStream();
        ImageIO.write(image, "JPEG", out);
        out.flush();
        out.close();
    }


    @AccessLimit
    @RequestMapping(value="/path", method=RequestMethod.GET)
    @ResponseBody
    public BaseResponse getMiaoshaPath(HttpServletResponse response, MiaoshaUser user,
                                    @RequestParam("goodsId")long goodsId,
                               @RequestParam(value="verifyCode", defaultValue="0")int verifyCode) throws Exception {

        boolean check = miaoshaOrderService.checkVerifyCode(user, goodsId, verifyCode);
        if(!check) {
            return BaseResponse.error("验证码错误");
        }
        String path  =miaoshaOrderService.createMiaoshaPath(user, goodsId);
        return BaseResponse.business(DefaultSuccessEnum.SUCCESS, path);
    }

    @RequestMapping(value="/result", method=RequestMethod.GET)
    @ResponseBody
    public BaseResponse miaoshaResult(Model model,MiaoshaUser user,
                                      @RequestParam("goodsId")long goodsId) {
        model.addAttribute("user", user);
        long result  =miaoshaOrderService.getMiaoshaResult(user.getId(), goodsId);
        return BaseResponse.business(DefaultSuccessEnum.SUCCESS, result);
    }

    @PostMapping("/{path}/miaosha")
    @ResponseBody
    public BaseResponse miaosha(@RequestParam("goodsId")Long goodsId, MiaoshaUser user,
                                @PathVariable("path")String path,
                                Model model){
        if(Objects.isNull(user)){
            return BaseResponse.error("请先登陆");
        }
        if(isGlobalActivityOver()){
            return BaseResponse.error("秒杀已结束");
        }
        boolean check = miaoshaOrderService.checkPath(user, goodsId, path);
        if(!check){
            return BaseResponse.error("验证码错误");
        }
        if(localOverMap.get(goodsId)){
            return BaseResponse.error("商品已秒杀完毕");
        }
        MiaoshaOrder miaoshaOrder = orderInfoService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if(Objects.nonNull(miaoshaOrder)){
            return BaseResponse.error("已经秒杀过了");
        }

        MiaoshaMessage mm = new MiaoshaMessage();
        mm.setUser(user);
        mm.setGoodsId(goodsId);
        amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE, JSON.toJSONString(mm));
        return BaseResponse.business(DefaultSuccessEnum.SUCCESS, 0);
    }

    @RabbitListener(queues = MQConfig.MIAOSHA_QUEUE)
    public void receive(String message){
        log.info("receive message:"+message);
        MiaoshaMessage mm  = JSONObject.parseObject(message, MiaoshaMessage.class);
        MiaoshaUser user = mm.getUser();
        long goodsId = mm.getGoodsId();

        GoodsVo goods = goodsService.queryGoodsVoByGoodsId(goodsId);
        int stock = goods.getStockCount();
        if(stock <= 0) {
            return;
        }
        //判断是否已经秒杀到了
        MiaoshaOrder order = miaoshaOrderService.queryOrderByUserIdAndGoodsId(user.getId(), goodsId);
        if(order != null) {
            return;
        }
        //减库存 下订单 写入秒杀订单
        miaoshaOrderService.miaosha(user, goods);
    }
}
